import type {IceAxiosInstance} from "@/http/index";
import {createAxios} from "@/http/index";
import type {JsonResult} from "@/typings/types";
import {CryptHelper} from "@/http/CryptHelper";
import type {AxiosRequestConfig} from "axios";
import type {AttachMore} from "@/typings/global";
import {useAppStore} from "@/stores/modulers/app";

export abstract class BaseApi<T> {
    abstract baseUrl: string;

    http: IceAxiosInstance;

    constructor() {
        this.http = createAxios<T>();
    }

    async getPublicKey() {
        const appStore = useAppStore();
        const res = await createAxios<any>().get("/auth/getPublicKey");
        if (res.data && res.ok) {
            appStore.setPublicKey(res.data);
        }
        return appStore.getData;
    }

    async safeRequest<T>(url: string, data?: any): Promise<JsonResult<T>> {
        const {keyId, publicKey} = await this.getPublicKey();
        const cryptHelper = new CryptHelper(keyId, publicKey);
        const nonceStr = cryptHelper.randomKeys();
        const timeUnit = new Date().getTime().toString();

        if (!data) {
            data = {};
        }

        data = JSON.parse(JSON.stringify(data));
        data.nonceStr = nonceStr;
        data.timeUnit = timeUnit;

        const sign = cryptHelper.signData(data);
        const rsaSign = cryptHelper.rsaEncrypt(sign);

        const headers = {
            "Content-Type": "application/json;charset=utf8",
            "x-requested-with": "XMLHttpRequest",
            keyId: keyId,
            clientType: "javascript",
            versionCode: 2,
            nonceStr: nonceStr,
            timeUnit: timeUnit,
            sign: rsaSign,
        };
        const body = cryptHelper.aesEncrypt(sign, JSON.stringify(data));
        return this.http.post(this.baseUrl + url, body, {headers: headers}).then(res => {
            if (res.data != null) {
                const aesDecrypt = cryptHelper.aesDecrypt(sign, res.data);
                res.data = JSON.parse(typeof aesDecrypt === "string" ? aesDecrypt : "");
            }
            return Promise.resolve(res);
        }).catch(resp => {
            return Promise.reject(resp);
        });
    }

    get<T>(url: string, config?: AxiosRequestConfig): Promise<JsonResult<T>> {
        return this.http.get(this.baseUrl + url, config) as Promise<JsonResult<T>>;
    }

    post(url: string, data?: any, config?: AxiosRequestConfig) {
        return this.http.post(this.baseUrl + url, data, config);
    }

    attachMore(params: AttachMore[]) {
        return this.http.post("/common/attachMore", params);
    }

    attachMoreFilter(attachMoreDTO: AttachMore, parentValue?: string, parentType?: string) {
        return this.http.post("/common/attachMoreFilter", {
            attachMoreDTO: attachMoreDTO,
            parentValue: parentValue,
            parentType: parentType,
        });
    }

}
